package com.atguigu.gulimall.search.thread;

import sun.plugin.com.event.COMEventHandler;

import java.util.Arrays;
import java.util.concurrent.*;

/**
 * @Description :测试线程
 * @Author : mayp
 * @Date: 2020-10-21 22:13
 */
public class ThreadTest {
//    创建一个容量为10的线程池
    public static ExecutorService service = Executors.newFixedThreadPool(10);

//    多任务组合
    public static void main(String[] args) throws ExecutionException, InterruptedException {
//        创建多个线程。也可以加上线程池
        CompletableFuture<String> futureImg = CompletableFuture.supplyAsync(()->{
            System.out.println("华为手机图片");
          return "华为.jpg";
        });
        CompletableFuture<String> futureAttr = CompletableFuture.supplyAsync(()->{
            try {
                Thread.sleep(1000);
                System.out.println("查询商品属性");
            } catch (InterruptedException e) {
                e.printStackTrace();
            }

            return "黑色+16G";
        });
        CompletableFuture<String> futureDesc = CompletableFuture.supplyAsync(()->{
            System.out.println("商品介绍");
            return "华为手机你值得拥有";
        });
//        让所有线程一起执行
        CompletableFuture<Void> future = CompletableFuture.allOf(futureAttr, futureDesc, futureImg);
//        CompletableFuture<Object> future = CompletableFuture.anyOf(futureAttr, futureDesc, futureImg);
        future.get(); // 等待所有结果都完成

        System.out.println("args = " + futureAttr.get()+"---"+futureDesc.get()+"---"+futureImg.get());
    }

//    线程池串行化
    public void threadChuanXing(String[] args) {


        /**
         *  线程池串行化
         *  1、thenRun:不能获取上一步的执行结果，无返回值
         *          .thenRunAsync(()->{
         *                 System.out.println("args = " + Arrays.deepToString(args));
         *               },service);
         *  2、能获取上一步的执行结果，无返回值
         *          .thenAcceptAsync(res -> {
         *             System.out.println("res = " + res);
         *         },service);
         *  3、能获取上一步的执行结果，有返回值
         *          .thenApplyAsync(res->{
         *             return "hello "+res;
         *         },service)
         */

        CompletableFuture<String> future = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程 = " + Thread.currentThread().getId());
            int i = 10 / 5;
            System.out.println("运行结果 = " + i);
            return i;
        }, service).thenApplyAsync(res->{
            return "hello "+res;
        },service);

        System.out.println("future = " + future);
    }

    public void threadPool2(String[] args) throws ExecutionException, InterruptedException {
//        1、没有返回值
//        CompletableFuture<Void> future = CompletableFuture.runAsync(() -> {
//            System.out.println("当前线程 = " + Thread.currentThread().getId());
//            int i = 10 / 2;
//            System.out.println(i);
//        }, service);

//        2、可以得到返回值
        CompletableFuture<Integer> future2 = CompletableFuture.supplyAsync(() -> {
            System.out.println("当前线程 = " + Thread.currentThread().getId());
            int i = 10 / 0;
            System.out.println(i);
            return i;
        }, service).whenComplete((res,exc)->{
            System.out.println("res = " + res+"。异常是："+exc);
        }).exceptionally(fn -> {
            System.out.println("fn = " + fn);
//            出现异常后，返回什么
            return 10;
        });

        Integer integer = future2.get();
        System.out.println("获取结果（肯定是返回的结果10） = " + integer);
    }

    public void threads(String[] args) {
        service.execute(new Runnable() {
            @Override
            public void run() {
                System.out.println("我是谁");
            }
        });

        /**
         * 1、线程池创建，准备好core数量的核心线程，准备接受任务
         * 2、core满了，就将再进来的任务放入阻塞队列中，空闲的core就会自己去阻塞队列获取任务执行
         * 3、阻塞队列满了，就直接开新线程执行，最大只能开到max指定的数量
         * 4、max满了就用RejectedExecutionHandler拒绝任务
         * 5、max都执行完成，有很多空闲，在指定的时间keepAliveTime以后，释放max-core这些线程
         *  new LinkedBlockingDeque<>() 默认是Integer的最大值内存不过
         *
         *  面试题
         *      一个线程池 core 7；max20；queue：50,；100并发进来了怎么分配
         *      7个会立即得到，50个进入队列，再开13个进行执行，剩下的30个就会使用拒绝策略。
         *      如果不想抛弃还要执行。CallerRunsPolicy
         */
        ThreadPoolExecutor executor = new ThreadPoolExecutor(5,
                200,
                10,
                TimeUnit.SECONDS,
                new LinkedBlockingDeque<>(10000),
                Executors.defaultThreadFactory(),
                new ThreadPoolExecutor.AbortPolicy());
//        Executors.newCachedThreadPool() core是0，所有都可以回收
//        Executors.newFixedThreadPool() 固定大小，core=max 都不可以回收
//        Executors.newScheduledThreadPool() 定时任务的线程池
//        Executors.newSingleThreadExecutor() 单线程的线程池，后台从队列里面获取任务，挨个执行

    }

}
